/* Copyright 2024 Coremail
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import notificationManager from '@ohos.notificationManager';
import wantAgent from '@ohos.app.ability.wantAgent';
import type { WantAgent } from '@ohos.app.ability.wantAgent';
import type Base from '@ohos.base';
import { cm } from '../util/queue/Queue';

/**
 * 每秒钟发送的通知数量不能很多,否则会导致闪退
 * TODO:
 * 目前是使用定时器发送通知,退到后台定时器会中止.
 * 定时同步也会遇到这个问题.
 */

export enum PermissionState {
  On,
  Off,
  Unkown
}

export interface NotifyParameter {
  account: string,
  folderFullName: string,
  mid: string,

  [key: string]: string
}

export interface NotifyItem {
  //识别是哪个用户的.
  account: string,

  //通知第一栏
  title: string,

  //第二栏
  text: string,

  //第三栏
  briefText: string,
  folderFullName: string,
  mid: string
}

/**
 * 通知栏管理
 */
export class NotifyManager {
  static notifyItems: NotifyItem[] = [];
  static noticeCount: number = 0;
  //是否申请了权限
  static permissionState: PermissionState = PermissionState.Unkown

  static requestPromise ?: Promise<void>;

  static queue: cm.Queue<NotifyItem> = new cm.Queue();

  static isNotifying: boolean = false;

  // static enqueue() {
  //
  // }
  //
  // static dequeue() {
  //
  // }

  /**
   * 请求权限并发送通知.
   * @param title
   * @param text
   * @param briefText
   */
  static async notify(item: NotifyItem): Promise<void> {
    switch (this.permissionState) {
      case PermissionState.On: {
        NotifyManager.queue.enqueue(item);
        NotifyManager.startNotifyWithInterval();
        break;
      }
      case PermissionState.Off: {
        //用户关闭权限,直接忽略不弹消息.
        NotifyManager.queue.clearAll();
        break;
      }
      case PermissionState.Unkown: {
        NotifyManager.doRequestPermission();
        NotifyManager.notify(item);
        break;
      }
    }
  }

  static async doRequestPermission(): Promise<void> {
    if (!NotifyManager.requestPromise) {
      NotifyManager.requestPromise = (async () => {
        await notificationManager.requestEnableNotification();
        let b = await notificationManager.isNotificationEnabled();
        NotifyManager.permissionState = b ? PermissionState.On : PermissionState.Off
      })()
    }
    await NotifyManager.requestPromise;
  }

  /**
   * 一下子弹出太多会导致崩溃?
   * 控制为100ms发送一次,1秒1次.
   * 在通知中,多次调用该函数,并不会产生多个推送队列.
   *
   * @param interval
   */
  static startNotifyWithInterval(interval: number = 1000) {
    if (NotifyManager.isNotifying) {
      //处理中,不另外开启

    } else {
      let item = NotifyManager.queue.dequeue();
      if (item) {
        NotifyManager.isNotifying = true;
        // try {
        NotifyManager.doNotify(item);
        // } catch (e) {
        //   let err = e as Error
        //   notifyLogger.debug(`[do nofity ${JSON.stringify(item)}][failed:${err.message}]`);
        // }

        setTimeout(() => {
          NotifyManager.notifyWithIntervalStep(interval);
        }, interval)
      } else {
        NotifyManager.isNotifying = false;
      }
    }
  }

  /**
   * 一次通知队列中的一次通知
   * @param interval
   */
  private static notifyWithIntervalStep(interval) {
    let item = NotifyManager.queue.dequeue();
    if (item) {
      NotifyManager.isNotifying = true;
      NotifyManager.doNotify(item);
      setTimeout(() => {
        NotifyManager.notifyWithIntervalStep(interval);
      }, interval)
    } else {
      NotifyManager.isNotifying = false;
    }
  }

  private static doNotify(item: NotifyItem): void {
    let notifyParameter: NotifyParameter = {
      folderFullName: item.folderFullName,
      mid: item.mid,
      account: item.account
    }
    let wantAgentInfo: wantAgent.WantAgentInfo = {
      wants: [
        {
          deviceId: '',
          bundleName: 'cn.coremail.chordmail',
          abilityName: 'MainAbility',
          action: 'locate_mail',
          entities: [],
          uri: '',
          parameters: notifyParameter
        }
      ],
      operationType: wantAgent.OperationType.START_ABILITY,
      requestCode: NotifyManager.noticeCount,
      wantAgentFlags: [wantAgent.WantAgentFlags.CONSTANT_FLAG]
    };

    wantAgent.getWantAgent(wantAgentInfo, (err: Base.BusinessError, data: WantAgent) => {
      if (err) {
        // notifyLogger.debug(`[notify ${item.title ?? ""},${item.text ?? ""},${item.briefText ??
        //   ""}] [get want] [failed:${err.message}]`);
        return;
      }
      //text为空字符串,notificationRequest发送会闪退.
      let notificationRequest: notificationManager.NotificationRequest = {
        content: {
          notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
          normal: {
            title: item.title ?? "",
            text: item.text ?? "",
            additionalText: item.briefText ?? "",
          },
        },
        id: NotifyManager.noticeCount,
        wantAgent: data,
      }
      notificationManager.publish(notificationRequest, (err: Base.BusinessError) => {
        if (err) {
          // notifyLogger.debug(`[notify item: [${item.title ?? ""}] [${item.text ?? ""}] [${item.briefText ??
          //   ""}] [publish] [failed:${err.message}]`)
          return
        }
      });
      NotifyManager.noticeCount++;
    });
  }

  static cancel(id: number): void {
    notificationManager.cancel(id)
  }

  static cancelAll(): void {
    notificationManager.cancelAll()
  }
}